# -*- coding:utf-8 -*-
import json_loader
import layout_algorithm


class Singleton(type):
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]


# container of network data
class NetworkData(object, metaclass=Singleton):

    def __init__(self):
        '''
        load the init json file
        '''
        self._firstJsonName = r"json/res0.json"
        self._network_history = []

        self._loader = json_loader.JsonLoader()
        network = self._loader.loadFirstImage(self._firstJsonName)

        # layout the graph
        layout = layout_algorithm.LayoutAlgorithmIGraph()
        layout.execute(network)

        self._network_history.append(network)
        self._network_pos = 0

        # 确定一共有多少帧
        self._network_frams_amount = 26

    def next(self):
        # maybe fail ,but self._pos is not move when fail
        if self._network_pos + 1 < len(self._network_history):
            self._network_pos += 1
            return self.current()
        else:
            # load new image json
            num = self._network_pos + 1
            filename = r"json/diff" + str(num) + ".json"
            network = self._loader.loadNextImage(self.current(), filename)

            if network:
                # layout the graph
                layout = layout_algorithm.LayoutAlgorithmFDL()
                layout.execute(network, self._network_history[self._network_pos]["nodes"])

                self._network_history.append(network)
                self._network_pos += 1
                return self.current()

        print("NetworkData out of range")
        return None

    def prev(self):
        if 0 <= self._network_pos - 1 < len(self._network_history):
            self._network_pos -= 1
            return self.current()

        print("NetworkData out of range")
        return None

    def current(self):
        return self._network_history[self._network_pos]

    def __len__(self):
        return len(self._network_history)

    def __getitem__(self, pos):
        if isinstance(pos, int) and 0 <= pos < len(self._network_history):
            return self._network_history[pos]
        print("NetworkData out of range")
        return None

    def getCurrentPos(self):
        return self._network_pos

    def getFramesAmount(self):
        return self._network_frams_amount


# container of vad data
class VadData(object, metaclass=Singleton):

    def __init__(self, pid, current_pos):
        '''
        load the init json file
        '''
        self._pid = pid
        self._vadtree_pos = current_pos

        self._JsonName = r"json/vad"+str(self._vadtree_pos)+".json"
        self._vadtree_history = {}

        self._loader = json_loader.JsonLoader()

    def current(self):
        if self._vadtree_pos in self._vadtree_history:
            if self._pid in self._vadtree_history[self._vadtree_pos]:
                return self._vadtree_history[self._vadtree_pos][self._pid]
            else:
                vadtree = self._loader.loadVadImage(self._JsonName, self._pid)

                # layout the graph
                layout = layout_algorithm.LayoutAlgorithmIGraph()
                layout.execute_vad(vadtree)

                self._vadtree_history[self._vadtree_pos].update({self._pid: vadtree})
                return self._vadtree_history[self._vadtree_pos][self._pid]
        else:
            self._JsonName = r"json/vad"+str(self._vadtree_pos)+".json"
            vadtree = self._loader.loadVadImage(self._JsonName, self._pid)

            # layout the graph
            layout = layout_algorithm.LayoutAlgorithmIGraph()
            layout.execute_vad(vadtree)

            self._vadtree_history[self._vadtree_pos] = {self._pid: vadtree}
            return self._vadtree_history[self._vadtree_pos][self._pid]

    def __len__(self):
        return len(self._vadtree_history)

    def __getitem__(self, pos):
        if isinstance(pos, int) and 0 <= pos < len(self._vadtree_history):
            return self._vadtree_history[pos]
        print("VadData out of range")
        return None

    def getCurrentPos(self):
        return self._vadtree_pos
